[s3] Avoid ListBucket requirement in snapshot commit path#8263
[s3] Avoid ListBucket requirement in snapshot commit path#8263hhhizzz wants to merge 11 commits into
Conversation
|
I think this still breaks commit conflict handling on object stores. The latest snapshot is read before acquiring the commit lock, and |
|
Thanks for catching this.The previous object-store branch could skip the stale snapshot guard and overwrite an existing I updated the PR to keep the no-overwrite conflict signal without requiring
Added regression tests for the stale commit conflict path and S3 412 handling. Verified with focused Maven tests, and with Ceph RGW using a temporary user without |
| // On object stores, probing a missing object can require list permission. Trust the | ||
| // committed hint and let the commit retry path handle a concurrently newer snapshot. | ||
| if (fileIO.isObjectStore()) { | ||
| return snapshotId; |
There was a problem hiding this comment.
This still falls back to listing when LATEST is absent (for example on the first commit of a new table, or after the hint file is lost). FileStoreCommitImpl calls snapshotManager.latestSnapshot() before it writes snapshot-1, so with an S3 user that has GetObject/PutObject but no ListBucket, an empty table will fail here before the new conditional PUT path is reached. The new object-store test writes LATEST first, so it does not cover this case. For object stores we need a no-list path for a missing hint as well, such as treating the missing hint as no latest snapshot and relying on the no-overwrite snapshot write to reject an unexpected existing snapshot-1.
This comment was marked as outdated.
This comment was marked as outdated.
4ce509a to
cd6b31f
Compare
|
Updated the branch with the current no-list first-snapshot logic and additional conflict coverage. The current behavior is:
I also explicitly checked the ambiguous damaged-metadata case: if both Validation:
|
| Optional<Long> latestHint = readLatestHintForNoListObjectStore(fileIO, LATEST, dir); | ||
| Long snapshotId = latestHint.orElse(null); | ||
| if (supportsNoListSnapshotCommit(fileIO, file, snapshotId)) { | ||
| return snapshotId == null |
There was a problem hiding this comment.
This no-list branch treats a missing LATEST hint as an empty table whenever EARLIEST is also absent. A normal table with existing snapshots can be in that state: snapshot commits only update LATEST, and EARLIEST is only written later by expiration/rollback paths. If the LATEST object is accidentally deleted or temporarily unreadable (the S3 no-ListBucket case this PR is handling), latestSnapshotId() now returns null instead of falling back to listing or failing closed, so readers/committers can treat a non-empty table as new and attempt snapshot-1 again. We should not return null solely because both hints are missing; either verify snapshot-1 is absent using the conditional-create/read path, fall back to list, or fail with the same recovery-required message.
Purpose
Fixes #8261.
Avoid requiring
ListBucketfor S3-compatible object-store snapshot commits, while preserving the stale snapshot conflict handling.The change skips the
exists(snapshot-N)probe on object stores, but writessnapshot-Nwith no-overwrite semantics. For S3 this usesIf-None-Match: *, and maps412 PreconditionFailedtoFileAlreadyExistsException, so stale commits retry instead of overwriting existing snapshot metadata.Non-object-store behavior is unchanged.
Tests
Added regression tests for:
exists(snapshot-N)snapshot-N412 PreconditionFailedis treated as the file-exists conflict signalVerified with:
Also verified against Ceph RGW with a temporary user without
ListBucket: first conditional PUT succeeds, second returns 412, and the original object